tree grammar HibernateTreeWalker;

options {
  language = Java;
  output = AST;
  tokenVocab = Yagdao;
  ASTLabelType = CommonTree;
 backtrack=true;
}

@header {
	package com.altuure.yagdao.grammar;
	import com.altuure.yagdao.common.YagdaoException;
	import com.altuure.yagdao.YOperator;
	import java.util.Map;
	import java.util.HashMap;
	import java.util.List;
	import java.util.LinkedList;

	import org.hibernate.NonUniqueResultException;
	import org.hibernate.Query;
	import org.hibernate.Session;
	import org.hibernate.Criteria;
	import org.hibernate.criterion.Criterion;
	import org.hibernate.criterion.MatchMode;
	import org.hibernate.criterion.ProjectionList;
	import org.hibernate.criterion.Projections;
	import org.hibernate.criterion.Restrictions;
	import org.hibernate.impl.CriteriaImpl;
}



@members{
    private Criteria root; 
    private Map<String,String> joins;
    private Object value=null;
    private int defaultOp=EQUALS;
    private boolean objectReferenced;
    
    public void init(Criteria root , Map<String, String> joins){
      this.root=root;
      this.joins=joins;
      
    }
   
    public void setValue(Object v){
      this.value=v;
      objectReferenced=false;
    }
    public void setDefaultOp(YOperator op){
    
         switch (op) {
        case NONE: defaultOp=EQUALS; break;
        case EQUAL:defaultOp=EQUALS;break;
        case GE:defaultOp=GREATER_OR_EQ;break;
        case GT:defaultOp=GREATER;break;
        case IN:defaultOp=IN;break;
        case LE:defaultOp=LESS_OR_EQ;break;
        case LIKE:defaultOp=LIKE;break;
        case ULIKE:defaultOp=ILIKE;break;
        case NOTLIKE:defaultOp=EQUALS;break;
        case NOTULIKE:defaultOp=EQUALS;break;
        case LT:defaultOp=LESS;break;
        case BETWEEN:defaultOp=BETWEEN;break;
        case ISNULL:defaultOp=ISNULL;break;
        case ISNOTNULL:defaultOp=ISNOTNULL;break;


        } 
    }
    
    
    private List<String> errors = new LinkedList<String>();
    public void displayRecognitionError(String[] tokenNames,
                                        RecognitionException e) {
        String hdr = getErrorHeader(e);
        String msg = getErrorMessage(e, tokenNames);
        errors.add(hdr + " " + msg);
    }
    public List<String> getErrors() {
        return errors;
    }
    public Criterion createExp(CommonTree tree,List args){
      return null;
    }
     
   
}

identifier returns [Criteria result] :{$result=root;} (op1=ID {$result=$result.createCriteria($op1.text);} DOT)* op2=ID {$result=$result.createCriteria($op2.text);}  ;



result_list :(DISTINCT)? result_col (COMMA result_col)* EOF!;
result_col: expression;

condition_col: HAVING? expression (condition expression?)? EOF!;
//backward compatible will be HAVING? expression condition expression?

group_col: expression (COMMA expression)* EOF!;

where_condition:  
     (LPAREN condition_seq RPAREN) =>inner_col
     |expression condition expression?
    
;
where_clause:
    condition_seq EOF!;

condition_seq: 
  where_condition (where_op where_condition)*;
       
having_col: where_condition (where_op where_condition)*;   

inner_col : LPAREN! condition_seq RPAREN!;

order_property:  expression order_op?;
order_clause:  order_property (COMMA order_property)* EOF!;

where_op
  : AND
    |OR
  ;
  
order_op
  : ASC|DESC
  ;


condition:    GREATER
              |LESS
              |EQUALS
              |EQUALS2
              |NOT_EQUALS
              |NOT_EQUALS2
              |LESS_OR_EQ
              |GREATER_OR_EQ
              |IN
              |NOT_IN
              |LIKE
              |ILIKE
              |ISNULL
              |ISNOTNULL
              |BETWEEN
              ;



term
  : identifier
  | LPAREN! expression RPAREN!
  | invocation 
  | QUESTION
  | INTEGER
  | FLOAT
  | STRING_LITERAL
  ;
  
unary
  : (PLUS! | negation^)* term
  ;

negation
  : MINUS -> NEGATION
  ;

mult
  : unary ((ASTERISK^ | SLASH^ | MOD^) unary)*
  ;
  
  
expression
  : mult ((PLUS^ | MINUS^) mult)*
  ;
invocation:  functionname LPAREN  argumentlist? RPAREN;
argumentlist: expression (COMMA expression)* ;

functionname
  : 
  AVG|MIN |MAX |SUM|COUNT
  |NEG|ABS|SQRT|TOFLOAT|TOINTEGER|TOLONG|TOBIGDECIMAL|TOBIGINTEGER|TOSTRING
  |CONCAT|SUBSTRING|TRIM|LOWER|UPPER|LENGTH|LOCATE
  |CURRENTDATE|CURRENTTIME|CURRENTTIMESTAMP
  |SECOND|MINUTE|HOUR|DAY|MONTH|YEAR
  |MOD
  |unknownFunctionName; 
unknownFunctionName: ID;      

    
